/*
 * Created on Feb 17, 2004
 *
 * Author: Sandeep Prakash
 * Project: Sucxentv2 (using leaf nodes only)
 */
// A class to contains a summary information of the current document
package dbsucxentW.storageW.parserW;


/**
 * @author Administrator
 *
 * 
 */
public class DocumentSummary {

    private int[] _cValues;	//Value of M: M[i]=_cValues[i-1]
    private int[] _cCounters;	//counter to count M: M[i]=_cValues[i-1] = max(_cCounters[i-1])
    private long[] _rValues;	//RValue': RValue'[i]=_rValues[i-1] (comment by k 20060626)
    private long[] ancestorValues;
    private int _numLeaves;
    //
    //Maximum depth of an XML document. This is just an
    //estimation. Actually calculated during parsing.
    private final static int MAX_DEPTH_EXPECTED = 20;
    private int _maxDepth = 0;
    private boolean _isSummarized = false;

    public DocumentSummary() {
        _cValues = new int[MAX_DEPTH_EXPECTED];
        _cCounters = new int[MAX_DEPTH_EXPECTED];
    }

    //to calculate maxDepth, should not use the branchOrder value! But the depth itself
    public void processNewLeaf(int branchOrder, int leafOrder, int currDepth) {
        if (currDepth - 1 > _maxDepth) {
            _maxDepth = currDepth - 1;
        }

        for (int i = 0; i < branchOrder; i++) {
            _cCounters[i]++;
        }

        for (int i = branchOrder; i < _maxDepth; i++) {
            // store current value in the counters to cValues
            if (_cCounters[i] > _cValues[i]) {
                _cValues[i] = _cCounters[i];
            }
            // reset counters
            // note that the initial value of the counters is 0, not 1. The first element is not counted.
            _cCounters[i] = 0;
        }
        _numLeaves = leafOrder;
    }

    public void summarize() {
        if (!_isSummarized) {
            //add the followings to make sure that _cValues is updated with the most recent value of _cCounters
            for (int i = 0; i < _maxDepth; i++) {
                if (_cCounters[i] > _cValues[i]) {
                    _cValues[i] = _cCounters[i];
                }
            }

            _rValues = new long[_maxDepth];
            _rValues[_maxDepth - 1] = 1;

            this.ancestorValues = new long[_maxDepth];
            this.ancestorValues[_maxDepth - 1] = 1;

            for (int i = _maxDepth - 2; i >= 0; i--) {
                _rValues[i] = _rValues[i + 1] * (_cValues[i + 1] * 2) + 1;
                ancestorValues[i] = ancestorValues[i + 1] * (_cValues[i + 1] + 1);
            }

            _isSummarized = true;
        }
    }

    public long getRValue(int depth) {
        if (depth == 0) {
            return 0;
        }
        return _rValues[depth - 1];
    }

    public long getAncestorValue(int depth) {
        if (depth == 0) {
            return 0;
        }
        return this.ancestorValues[depth - 1];
    }

    public int getMaxDepth() {
        return _maxDepth;
    }
}
